package com.gk.panda.apis.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gk.panda.apis.Vo.RealtimeShootListVo;
import com.gk.panda.apis.Vo.RealtimeShootVo;
import com.gk.panda.apis.Vo.exports.ExportAreaUserCountVO;
import com.gk.panda.apis.entity.TransectManager.vo.EquipmentPointVo;
import com.gk.panda.apis.entity.largeScreen.Enum.OrgEnum;
import com.gk.panda.apis.entity.largeScreen.dto.PatrolInfoDto;
import com.gk.panda.apis.entity.largeScreen.dto.PatrolListDto;
import com.gk.panda.apis.entity.largeScreen.vo.AreaPatrolInfo;
import com.gk.panda.apis.entity.largeScreen.vo.EcologicalEqVo;
import com.gk.panda.apis.entity.largeScreen.vo.PersonCountHistoryDataVo;
import com.gk.panda.apis.mapper.EquipmentPointMapper;
import com.gk.panda.apis.mapper.LargeScreenMapper;
import com.gk.panda.apis.patrol.servicr.PatrolService;
import com.gk.panda.apis.patrol.servicr.ReportService;
import com.gk.panda.apis.service.*;
import com.gk.panda.apis.util.excel.ExcelUtils;
import com.gk.panda.commons.exception.ServerException;
import com.gk.panda.pojo.*;
import com.gk.panda.pojo.patrol.dto.DetailListDTO;
import com.gk.panda.pojo.patrol.entity.PatrolEntity;
import com.gk.panda.pojo.patrol.entity.ReportEntity;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class LargeScreenServiceImpl implements LargeScreenService {

    private static final String FILE_SUFFIX = ".xlsx";

    @Autowired
    private OrgService orgService;

    @Autowired
    private LargeScreenMapper largeScreenMapper;

    @Autowired
    private DeviceManagerService deviceManagerService;

    @Autowired
    private ReportService reportService;

    @Autowired
    private PatrolService patrolService;

    @Autowired
    private EquipmentPointMapper equipmentPointMapper;

    @Autowired
    private RealtimeShootService realtimeShootService;

    @Autowired
    private AreaUserCountService areaUserCountService;

    @Autowired
    private DeviceHandheldTerminalService deviceHandheldTerminalService;

    @Autowired
    private BiologyFileService biologyFileService;

    /**
     * 大屏根据机构id获取抓拍和巡护事件
     * @param orgId
     * @return
     */
    @Override
    public List<RealtimeShoot> getEventByOrgId(Integer orgId,Integer pageSize,Integer includePatrol) {
        if (orgId == null) orgId = OrgEnum.CHENGDU.getOrgId();
        if (pageSize == null) pageSize = 20;
        QueryWrapper<RealtimeShoot> wrapper = new QueryWrapper<>();
        if (includePatrol == 1) {
            List<String> deviceSns = deviceManagerService.getDeviceSnListByOrgId(orgId);
            wrapper.in("device_sn",deviceSns).orderByDesc("get_time")
                    .last("limit 0,"+pageSize);
            return realtimeShootService.list(wrapper);
        } else {
            List<Integer> orgIds = orgService.getPuisneOrgIds(orgId);
            wrapper.in("org_id",orgIds).orderByDesc("get_time")
                    .last("limit 0,"+pageSize);
            return realtimeShootService.list(wrapper);
        }

//        List<EventVo> eventVos = largeScreenMapper.getRealtimeShootByOrgId(deviceSns,pageSize);
//        return eventVos;
    }

    /**
     * 大屏根据设备编号获取抓拍和事件
     * @param deviceSn
     * @return
     */
    @Override
    public Page<RealtimeShootListVo> getEventByDeviceSn(String deviceSn, Integer pageSize, Integer pageNumber) {
        if (pageSize == null) pageSize = 20;
        QueryWrapper<RealtimeShoot> wrapper = new QueryWrapper<>();
        wrapper.eq("device_sn",deviceSn).orderByDesc("get_time");
//                .last("limit 0,"+pageSize);
        List<RealtimeShoot> realtimeShoots = realtimeShootService.list(wrapper);
        //如果是利旧相机，无法自动回传，则从动植物图片视频中查询关联资源返回
        if (CollectionUtils.isEmpty(realtimeShoots)) {
            List<BiologyFile> biologyFiles = biologyFileService.list(Wrappers.<BiologyFile>lambdaQuery().eq(BiologyFile::getDeviceCode, deviceSn).orderByDesc(BiologyFile::getShootingTime));
            if (CollectionUtils.isNotEmpty(biologyFiles)) {
                biologyFiles.forEach(biologyFile -> {
                    RealtimeShoot realtimeShoot = new RealtimeShoot();
                    realtimeShoot.setDeviceSn(biologyFile.getDeviceCode());
                    realtimeShoot.setPath(biologyFile.getUrl());
                    realtimeShoot.setOrgId(biologyFile.getOrgId());
                    realtimeShoot.setLat(biologyFile.getLat());
                    realtimeShoot.setLot(biologyFile.getLot());
                    realtimeShoot.setGetTime(biologyFile.getShootingTime());
                    realtimeShoots.add(realtimeShoot);
                });
            }
        }
        List<RealtimeShootListVo> vos = new ArrayList<>();
        for (RealtimeShoot realtimeShoot : realtimeShoots) {
            RealtimeShootListVo vo = new RealtimeShootListVo();
            List<RealtimeShootVo> list = new ArrayList<>();
            RealtimeShootVo shootVo = new RealtimeShootVo();
            BeanUtils.copyProperties(realtimeShoot, shootVo);
            list.add(shootVo);
            vo.setRealtimeShootVos(list);
            vos.add(vo);
        }
        //当前页
        int current = pageNumber;
        //每页数据条数
        int size = pageSize;
        Page<RealtimeShootListVo> page = new Page<>(current, size);
        int count = vos.size();
        List<RealtimeShootListVo> pageList = new ArrayList<>();
        //计算当前页第一条数据的下标
        int currId = current > 1 ? (current - 1) * size : 0;
        for (int i = 0; i < size && i < count - currId; i++) {
            pageList.add(vos.get(currId + i));
        }
        page.setSize(size);
        page.setCurrent(current);
        page.setTotal(count);
        //计算分页总页数
        page.setPages(count % 10 == 0 ? count / 10 : count / 10 + 1);
        page.setRecords(pageList);
        return page;
    }

    /**
     * 大屏获取生态设备信息
     * @return
     */
    @Override
    public EcologicalEqVo getEcologicalEquipment() {
        EcologicalEqVo vo = new EcologicalEqVo();
        QueryWrapper<DeviceManager> wrapper = new QueryWrapper<>();
        wrapper.eq("model_type","ecological_equipment").eq("del_flag",0);
        List<DeviceManager> devices = deviceManagerService.list(wrapper);
        int online = 0;
        int offline = 0;
        for (DeviceManager device : devices) {
            if (device.getDeviceStatus() == 0) {
                online += 1;
            } else {
                offline += 1;
            }
        }
        vo.setDevices(devices);
        vo.setOnline(online);
        vo.setOffline(offline);
        return vo;
    }

    /**
     * 大屏获取巡护统计
     * @param dto
     * @return
     */
    @Override
    public List<AreaPatrolInfo> getPatrolInfo(PatrolInfoDto dto) {
        List<AreaPatrolInfo> infos = new ArrayList<>();
        OrgEnum[] orgEnums = OrgEnum.values();
            for (OrgEnum orgEnum : orgEnums) {
                List<Integer> orgIds = orgService.getPuisneOrgIds(orgEnum.getOrgId());
                AreaPatrolInfo areaPatrolInfo = largeScreenMapper.getPatrolInfo(orgIds,dto);
                if (areaPatrolInfo!=null){
                    areaPatrolInfo.setAreaName(orgEnum.getName());
                    if(dto.getPatrolType() !=null && dto.getPatrolType().equals("TRANSECT")) {
                        Integer num = largeScreenMapper.getTransectCover(orgIds, dto);
                        Integer transectNum = largeScreenMapper.getTransectNumByOrgIds(orgIds);
                        areaPatrolInfo.setPatrolNum(num + "-" + transectNum);
                    } else {
                        areaPatrolInfo.setPatrolNum(areaPatrolInfo.getNum().toString());
                    }

                    infos.add(areaPatrolInfo);
                } else {
                    areaPatrolInfo = new AreaPatrolInfo();
                    areaPatrolInfo.setAreaName(orgEnum.getName());
                    infos.add(areaPatrolInfo);
                }
            }

        return infos;
    }

    /**
     * 大屏根据巡护事件编号获取对应巡护信息
     * @param reportNum
     * @return
     */
    @Override
    public DetailListDTO getPatrolInfoByReportNum(String reportNum) {
        QueryWrapper<ReportEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("report_num",reportNum);
        ReportEntity reportEntity = reportService.getOne(wrapper);
        return patrolService.getPatrolById(reportEntity.getPatrolId());
    }

    /**
     * 大屏根据设备编号获取设备点位详情
     * @param deviceSn
     * @return
     */
    @Override
    public EquipmentPointVo getEquipmentPointBySn(String deviceSn) {
        return equipmentPointMapper.getEquipmentPointBySn(deviceSn);
    }

    /**
     * 大屏通过机构和巡护方式获取巡护记录
     * @param dto
     * @return
     */
    @Override
    public List<PatrolEntity> getPatrolList(PatrolListDto dto) {
        if (dto.getOrgId() == null) dto.setOrgId(OrgEnum.CHENGDU.getOrgId());
        if (dto.getPageSize() == null) dto.setPageSize(20);
        List<Integer> orgIds = orgService.getPuisneOrgIds(dto.getOrgId());
//        orgIds.remove(OrgEnum.CHENGDU.getOrgId());
        QueryWrapper<PatrolEntity> wrapper = new QueryWrapper<>();
        wrapper.in("total_org_id",orgIds)
                .eq(StringUtils.isNotEmpty(dto.getPatrolType()),"type",dto.getPatrolType())
                .gt(dto.getStartTime() != null,"end_time",dto.getStartTime())
                .lt(dto.getEndTime() !=null,"end_time",dto.getEndTime())
                .orderByDesc("create_time")
                .last("limit 0," + dto.getPageSize());
        List<PatrolEntity> patrolEntities = patrolService.list(wrapper);
        for (PatrolEntity patrolEntity : patrolEntities) {
            Integer totalOrgId = orgService.getTotalOrgId(patrolEntity.getTotalOrgId());
            patrolEntity.setTotalOrgId(totalOrgId);
        }
        return patrolEntities;
    }

    /**
     * 大屏获取实时直播视频地址列表
     * @return
     */
    @Override
    public List<String> getLiveVideo() {
        return deviceManagerService.getLiveVideo();
    }

    /**
     * 大屏获取人次统计历史数据
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<PersonCountHistoryDataVo> getPersonCountHistoryData(String startTime, String endTime) {
        List<PersonCountHistoryDataVo> vos = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Calendar currCal=Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        currCal.clear();
        currCal.set(Calendar.YEAR,currentYear);
        Date firstDayOfYear = currCal.getTime();
        currCal.clear();
        currCal.set(Calendar.YEAR,currentYear);
        currCal.roll(Calendar.DAY_OF_YEAR,-1);
        Date lastDayOfYear = currCal.getTime();
        if (startTime == null) startTime = sdf.format(firstDayOfYear);
        if (endTime == null) endTime = sdf.format(lastDayOfYear);
        QueryWrapper<AreaUserCount> wrapper = new QueryWrapper<>();
        wrapper.ge("time",startTime).le("time",endTime);
        List<AreaUserCount> areaUserCounts = areaUserCountService.list(wrapper);
        Map<String, List<AreaUserCount>> collect = areaUserCounts.stream().collect(Collectors.groupingBy(AreaUserCount::getAreaType));
        for(Map.Entry<String,List<AreaUserCount>> entry : collect.entrySet()) {
            PersonCountHistoryDataVo vo = new PersonCountHistoryDataVo();
            String areaType = entry.getKey();
            List<AreaUserCount> counts = entry.getValue();
            int personCount = 0;
            for (AreaUserCount count : counts) {
                personCount += count.getNum();
            }
            vo.setAreaType(areaType);
            vo.setCount(personCount);
            vos.add(vo);
        }
        return vos;
    }

    /**
     * 大屏获取手持终端个数
     * @return
     */
    @Override
    public Long getDeviceHandheldTerminalCount() {
        return deviceHandheldTerminalService.count();
    }

    /**
     * 大屏导出区域人数统计历史数据
     * @param startTime
     * @param endTime
     * @param response
     */
    @Override
    public void exportAreaUserCount(String startTime, String endTime, HttpServletResponse response) {
        QueryWrapper<AreaUserCount> wrapper = new QueryWrapper<>();
        wrapper.ge("time",startTime).le("time",endTime);
        List<AreaUserCount> areaUserCounts = areaUserCountService.list(wrapper);
        if (CollectionUtils.isEmpty(areaUserCounts)) {
            throw new ServerException("暂无数据导出！");
        }
        List<String> times = areaUserCounts.stream().map(AreaUserCount::getTime).distinct().collect(Collectors.toList());
        List<ExportAreaUserCountVO> vos = new ArrayList<>();
        times.forEach(time -> {
            ExportAreaUserCountVO vo = new ExportAreaUserCountVO();
            try {
                Date fm = new SimpleDateFormat("yyyyMMdd").parse(time);
                String format = new SimpleDateFormat("yyyy-MM-dd").format(fm);
                vo.setTime(format);
                List<AreaUserCount> list = areaUserCounts.stream().filter(areaUserCount -> areaUserCount.getTime().equals(time)).collect(Collectors.toList());
                list.forEach(a -> {
                    if (a.getAreaType().equals("core")) {
                        vo.setCoreNum(a.getNum());
                    } else {
                        vo.setGeneralNum(a.getNum());
                    }
                });
                vo.setTotal(vo.getCoreNum()+vo.getGeneralNum());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            vos.add(vo);
        });
        // 导出
        ExportParams params = new ExportParams();
        params.setSheetName("区域人数统计");
        params.setHeight((short) 15);
        Workbook workbook = ExcelExportUtil.exportBigExcel(params, ExportAreaUserCountVO.class, vos);
        ExcelExportUtil.closeExportBigExcel();
        // 生成文件
        String downloadFileName = "区域人数统计导出" + FILE_SUFFIX;
        ExcelUtils.download(downloadFileName, workbook, response);
    }
}
